package service;

import lombok.extern.slf4j.Slf4j;
import util.JankExecutors;

import java.util.concurrent.*;

/**
 * @author jiangnk
 * @since 2018-12-12
 */
@Slf4j
public class ThreeMethodThread {

    public static void main(String[] args) {
        ExecutorService executor = JankExecutors.newFixedSizeExecutorPool(5,"jank");

        /*
         * 测试实现一个线程的三种方式
         * extends Thread
         * implements Runnable
         * implements Callable<String>
         * callable和runnable的区别
         *      callable 调用 call() runnable 调用 run()
         *      callable 可以有返回值，可以捕捉异常，runnable不行
         *      callable since jdk1.5， runnable since 1.0
         *
         */
        executor.submit(new ByExtendThread());
        executor.submit(new ByImplementRunnable());
        Future<String> f = executor.submit(new ByImplementCallable());

        ExecutorService executorService = Executors.newCachedThreadPool();

        testLambdaThread(executor);

        try {
            // 获取线程执行结果，调用的时候会阻塞主进程
            log.info(f.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error(e.getMessage());
        }

        JankExecutors.shutdown(executor);
    }

    private static void testLambdaThread(ExecutorService executor){
        executor.submit(()->log.info("lambda thread runnable"));
        Future<String> lambdaThreadCallable = executor.submit(() -> {
            log.info("lambda thread callable");
            return "lambda thread callable";
        });
        try {
            log.info(lambdaThreadCallable.get());

            // 单独启动一个callable线程
            Callable<String> strCallable = () -> {log.info("future callable");return "future callable";};
            FutureTask<String> futureTask = new FutureTask<>(strCallable);
            futureTask.run();
            log.info(futureTask.get());

        } catch (InterruptedException | ExecutionException e) {
            log.error(e.getMessage());
        }

    }

    static class ByExtendThread extends Thread{
        @Override
        public void run(){
            log.info(Thread.currentThread().getName() + " ByExtendThread");
        }
    }

    static class ByImplementRunnable implements Runnable{

        @Override
        public void run() {
            log.info(Thread.currentThread().getName() + " ByImplementRunable");
        }
    }

    static class ByImplementCallable implements Callable<String>{

        @Override
        public String call() throws Exception {
            log.info(Thread.currentThread().getName() + " ByImplementCallable");
            return " thread ByImplementCallable";
        }
    }


}
